[LeetCode 5]Longest Palindromic Substring 最长回文子串
问题描述:
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
说明:解集不能包含重复的子集。
示例1:
1 | 输入: "babad" |
示例2:
1 | 输入: "cbbd" |
Solution:
Solution 1:
之前的考虑,最长回文字符串即字符串与倒置的字符串的最长公共字符串,但是并不正确,考虑acbca;最长公共子字符串dp解法时间复杂度为O(2),dp[i][j]表示从i到j的最长公共子字符串,字符串p1…..pi,q1…..qj转移方程:i/j=0,dp[i][j]=0;q[i]==p[j],dp[i][j]=dp[i-1][j-1]+1;q[i]!=p[j],dp[i][j]=0;
Code:
1 |
|
Solution 2:
最长回文字符串也有dp做法,不过复杂度也为O(2),所以我选择选择复杂度为线性的manacher算法。manacher算法是基于由中心向两边发散的算法,所以奇偶字符串处理不同,这里采用一个小技巧,在字符串首尾,及各字符间各插入一个未出现的字符使其恒为为奇字符串。定义一个辅助数组int p[],其中p[i]表示以 i 为中心的最长回文的半径,
设置两个变量,mx 和 id 。mx 代表以 id 为中心的最长回文的右边界,也就是mx = id + p[id]。
假设我们现在求p[i],也就是以 i 为中心的最长回文半径,如果i < mx,如上图,那么:1
2if (i < mx)
p[i] = min(p[2 * id - i], mx - i);
2 * id - i为 i 关于 id 的对称点,即上图的 j 点,而p[j]表示以 j 为中心的最长回文半径,因此我们可以利用p[j]来加快查找。
Code:
1 |
|